package com.eidos.blogs.openapi.thread.seckill;

import com.eidos.blogs.openapi.exception.AsyncMapperException;

import java.lang.reflect.Method;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author ： Eidos
 * @date ：Created in 2021/1/19
 * @description：
 * @modified By：
 * @version: 1.0
 */

public class AsyncMapperExecutor {
    private static int MAX_QUEUE_SIZE;

    private static int CORE_POOL_SIZE;

    private static int MAX_POOL_SIZE;

    private static String THREAD_NAME;

    private static volatile ThreadPoolExecutor executorService = null;

    /**
     * 初始化异步db执行线程
     *
     * @param corePoolSize
     * @param maxPoolSize
     * @param queueSize
     */
    public static void init(int corePoolSize, int maxPoolSize, int queueSize, String threadName) {
        CORE_POOL_SIZE = corePoolSize;
        MAX_POOL_SIZE = maxPoolSize;
        MAX_QUEUE_SIZE = queueSize;
        THREAD_NAME = threadName;
        init();
    }


    public static void init() {
        if (executorService == null) {
            executorService = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, 60L, TimeUnit.SECONDS,
                    new LinkedBlockingQueue<>(MAX_QUEUE_SIZE), new ThreadFactory() {
                private AtomicInteger counter = new AtomicInteger(1);

                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r);
                    t.setName(THREAD_NAME + counter.getAndIncrement());
                    t.setDaemon(false);
                    return t;
                }
            });
        }
    }

    /**
     * 异步执行一个任务
     *
     * @param mapper
     * @param method
     * @param args
     * @param callback
     */
    public static <T> void executeRunnable(Object mapper, Method method, T args, TaskBackHandler callback) {
        checkNull();
        AsyncMapperTask executor = new AsyncMapperTask(mapper, method, args, callback);
        executorService.execute(executor);
    }


    private static void checkNull() {
        if (executorService == null) {
            throw new AsyncMapperException("数据库异步执行线程需要初始化");
        } else {
            init(10, 50, 100, Thread.currentThread().getName());
        }
    }
}